Release 10.1A: OpenEdge Development:
Progress Dynamics Basic Development


Creating a filter viewer for a TreeView window

You can create a custom viewer to display at the top of the TreeView window. This viewer can contain any combination of fields appropriate to let the user select one or more records to start the TreeView at the top level. It is important to allow some sort of filtering if the number of records at the top level is not small (ideally one in most cases). The TreeView control is an ActiveX control independent of the Progress 4GL. To populate it, a TreeView method must be called repeatedly for each new node. If there are hundreds of nodes in the tree, it will be very slow to initialize. Also, a TreeView with many nodes is unlikely to provide an effective user interface, since the user will have to scroll around in the TreeView so much that it will be difficult to locate the nodes of interest. In a sense, this applies to all levels of the tree. If any node defines a data set that could be many records for a single record at the next level up, then the TreeView might not be the appropriate visualization to use.

As described earlier, the TreeView can receive foreign key values from another object and use them to identify the starting record at the top level. If this is not the case, then a filter viewer is likely the best mechanism to use to identify where to start.

Create the filter viewer as you would any other static viewer in the AppBuilder.

To build a filter viewer:

  1. Select the SDO for the top-level node.
  2. Choose one or more fields from the table to use in filtering. In some cases, you might not wind up using any fields from the table itself. This might happen if, for example, you want to define two fill-ins to use in a From-To range check or some other mechanism that does not directly use the fields in the database table. If this is the case, then select one field in the viewer wizard, and then delete it when you are done with the wizard.
  3. Back in the design window, you can define whatever fill-ins and other objects you need.

For the example, you build a viewer on the Department table that has the DeptCode and DeptName fields in it. When the user enters either a Department Code or a (possibly partial) Department Name and leaves that field, the viewer notifies the TreeView procedure and the TreeView is populated. The notification is done by means of a special published event defined for the TreeView, filterDataAvailable.

Figure 9–9 shows what the viewer looks like (with a text prompt added to it).

Figure 9–9: Example SmartDataViewer

First, you must ensure that the filter fields will be enabled when the TreeView comes up. To do this, you must intercept the initialization of the viewer and add a statement to enable the fields.

To override the initialization procedure:

  1. In the Section Editor of the AppBuilder, select Procedures New Override.
  2. Select the procedure name initializeObject. This is the standard named event that is run whenever this or any other SmartObject is initialized. By default, the procedure runs its standard code by executing a RUN SUPER statement, as the standard behavior is defined in a set of super procedures associated with this object.
  3. Add the ENABLE statement to this procedure. The standard Progress frame name for all visual SmartObjects is encoded in the preprocessor value {&FRAME-NAME}, so you qualify the reference with that name. Also, because the viewer is using the same temp-table definition to represent the data as it is sent from server to client by the SDO, you must qualify at least the first field reference with that temp-table name, RowObject as shown in the following code example:
  4. /*--------------------------------------------------------------------- 
     Purpose:   Make sure the fields in the viewer are enabled 
     Parameters:  
     Notes:     
    ---------------------------------------------------------------------*/ 
     /* Code placed here will execute PRIOR to standard behavior. */ 
     RUN SUPER. 
     ENABLE RowObject.DeptCode DeptName WITH FRAME {&FRAME-NAME}. 
     /* Code placed here will execute AFTER standard behavior.  */ 
    END PROCEDURE. 
    

    Note: If you are not already familiar with building applications with SmartObjects, you can learn a great deal more from the OpenEdgeŽ documentation.

Next, you must add the code to respond to the data the user enters and pass it on to the TreeView. The TreeView is subscribed to the filterDataAvailable event in this viewer. All you need to do is publish that event with the proper parameter. The way you have defined the filter viewer, the user can enter either a Department Code or a Department Name. So, you must define a LEAVE trigger for both of those fields. First, the DeptCode trigger checks that the user entered a value and publishes filterDataAvailable, passing a single input parameter. This parameter is a string consisting of the following values, in a comma-separated list:

To improve the user interface at run time:

  1. Before publishing the event, invoke the SESSION method SET-WAIT-STATE, which changes the mouse cursor. The General setting changes it to an hourglass to let the user know that the TreeView is processing the request.
  2. After the event, set the wait state back to “”, which restores the mouse cursor to what it was before. The following example shows the DeptCode trigger:
  3. DO: 
     IF RowObject.DeptCode:SCREEN-VALUE NE "0" AND 
       RowObject.DeptCode:SCREEN-VALUE NE "" THEN 
     DO: 
       SESSION:SET-WAIT-STATE("General"). 
       PUBLISH "filterDataAvailable"  
            (INPUT "DeptCode," + RowObject.DeptCode:SCREEN-VALUE + ",="). 
       SESSION:SET-WAIT-STATE(""). 
     END. 
    END. 
    

  4. Define a similar trigger for the DeptName field. Specify BEGINS as the operator so that the user can enter a partial value for the Department Name, as shown:
  5. DO: 
     IF RowObject.DeptName:SCREEN-VALUE NE "" THEN 
     DO: 
       SESSION:SET-WAIT-STATE("General"). 
       PUBLISH "filterDataAvailable"  
            (INPUT "DeptName," + RowObject.DeptName:SCREEN-VALUE +  
                ",BEGINS"). 
       SESSION:SET-WAIT-STATE(""). 
     END. 
    END. 
    

There are several different places in the viewer code where this trigger might belong, depending on the objects in the viewer:


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095